import os
import yaml
from typing import Dict, Any
from pathlib import Path
import logging

logger = logging.getLogger(__name__)

class ConfigurationManager:
    _instance = None
    _config: Dict[str, Any] = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(ConfigurationManager, cls).__new__(cls)
            cls._instance._initialize()
        return cls._instance

    def _initialize(self):
        """初始化配置"""
        try:
            # 获取配置文件路径
            base_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
            base_config_path = os.path.join(base_dir, 'config', 'base.yaml')
            env_config_path = os.path.join(base_dir, 'config', 'environment.yaml')
            
            # 加载基础配置
            with open(base_config_path, 'r', encoding='utf-8') as f:
                self._config = yaml.safe_load(f)
                
            # 加载环境配置（如果存在）
            if os.path.exists(env_config_path):
                with open(env_config_path, 'r', encoding='utf-8') as f:
                    env_config = yaml.safe_load(f)
                    env = os.getenv('ENV', 'development')
                    if env in env_config:
                        self._config.update(env_config[env])
            
            # 验证必要的配置项
            self._validate_config()
            
            # 创建必要的目录
            self._create_directories()
            
            logger.info(f"Configuration loaded successfully from {base_config_path}")
            
        except Exception as e:
            logger.error(f"Failed to load configuration: {str(e)}")
            raise

    def _validate_config(self):
        """验证配置项"""
        required_configs = {
            'database': ['type', 'host', 'port', 'username', 'password', 'database'],
            'storage': ['base_path', 'temp_path'],
            'download': ['chunk_size', 'max_threads', 'timeout', 'retry_times']
        }
        
        for section, fields in required_configs.items():
            if section not in self._config:
                raise ValueError(f"Missing required section: {section}")
            
            section_config = self._config[section]
            for field in fields:
                if field not in section_config:
                    raise ValueError(f"Missing required field: {section}.{field}")

    def _create_directories(self):
        """创建必要的目录"""
        try:
            # 创建存储目录
            storage = self._config.get('storage', {})
            for path_key in ['base_path', 'temp_path']:
                if path := storage.get(path_key):
                    Path(path).mkdir(parents=True, exist_ok=True)
            
            # 创建日志目录
            if log_path := self._config.get('logging', {}).get('file_path'):
                Path(log_path).mkdir(parents=True, exist_ok=True)
                
            # 创建下载目录
            if download_path := self._config.get('download_path'):
                Path(download_path).mkdir(parents=True, exist_ok=True)
                
        except Exception as e:
            raise Exception(f"Error creating directories: {e}")

    def _parse_value(self, value: Any) -> Any:
        """解析配置值，处理特殊表达式"""
        if isinstance(value, str):
            # 处理数学表达式
            if '*' in value:
                try:
                    return eval(value, {'__builtins__': {}})
                except:
                    return value
        return value

    def get_value(self, key: str, default: Any = None) -> Any:
        """获取配置项"""
        try:
            parts = key.split('.')
            value = self._config
            for part in parts:
                if isinstance(value, dict):
                    value = value.get(part, default)
                else:
                    return default
            return self._parse_value(value)
        except Exception as e:
            logger.warning(f"Error getting config value for key '{key}': {str(e)}")
            return default

    @property
    def config(self) -> Dict[str, Any]:
        """获取完整配置"""
        return self._config


# 创建全局配置实例
config = ConfigurationManager()